#ifndef __MEDIA_MESSAGE_H__
#define __MEDIA_MESSAGE_H__

#include <stdbool.h>
#include "video_cmd.h"
#include "libutils2/message_queue.h"

enum message_type {
	MESSAGE_TYPE_NONE = 0,
	MESSAGE_TYPE_NOTIFY = 0,
	MESSAGE_TYPE_VIDEO_FRAME,
	MESSAGE_TYPE_MEDIA_PKT,
	MESSAGE_TYPE_MEDIA_STREAM,
	MESSAGE_TYPE_CMD,

	MAX_MESSAGE_TYPE_COUNT,
};

struct message_context {
	enum message_type type;
	int16_t angle;
	pthread_spinlock_t spin;
	volatile int ref_cnt;
	void* handle;
	void (*put_context)(void* handle, struct message_context* context);

	union {
		struct media_packet* pkt;
		struct video_frame* frame;
		struct video_cmd* cmd;
		struct media_stream* stream;
	}data;
};


struct video_message {
	struct message msg;
	pthread_spinlock_t spin;
	volatile int ref_cnt;
	void* handle;
	void (*put_message)(void* handle, struct video_message* message);

	struct message_context* ctx;
};


extern struct video_message* video_message_alloc(void);
extern void video_message_free(struct video_message* message);
extern void video_message_get(struct video_message* message);
extern void video_message_put(struct video_message* message);

extern struct message_queue* video_message_queue_open(void);

/*
 * @brief: destory video message queue
 * @param: [in] struct video_message_queue_param* init_param
 * @remark: not thread safel!
 */
extern void video_message_queue_close(struct message_queue* queue);

extern struct message_context* video_message_queue_receive(struct message_queue* queue);

extern int video_message_queue_send(struct message_queue* queue, struct message_context* ctx);

/* 获取队列长度 */
extern int video_message_queue_size(struct message_queue* queue);
/* 判断队列是否为空 */
extern bool video_message_queue_is_empty(struct message_queue* queue);

extern void video_message_context_get(struct message_context* message_context);

extern void video_message_context_put(struct message_context* message_context);
extern void video_message_context_data_put(struct message_context* message_context);;
extern void video_message_context_put_all(struct message_context* message_context);
extern struct message_context* video_message_context_alloc(void);
extern int media_stream_message_send(struct message_queue* queue, struct media_stream* stream);

extern int media_notify_message_send(struct message_queue* queue);
extern int media_frame_message_send(struct message_queue* queue, struct video_frame* frame, int16_t angle);
extern int media_send_action_cmd(enum video_action action, enum action_cmd action_cmd, uint8_t* data, size_t size);
#endif
